﻿//TODO: Test Susan

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// Classical susan filter
    /// </summary>
    public class Susan : BaseImageFilter, ICornerFinder
    {
        protected List<Point> m_aPoint = new List<Point>();
        protected int[,] m_aMask = new int[,]{
                        {-1,-3},{0,-3},{1,-3},
                {-2,-2},{-1,-2},{0,-2},{1,-2},{2,-2},
       {-3,-1},{-2,-1},{-1,-1},{0, -1},{1, -1},{2, -1},{3, -1},
       {-3, 0},{ 2, 0},{-1, 0},{0, 0},{1, 0},{2, 0},{3, 0},
       {-3, 1},{-2, 1},{-1, 1},{0, 1},{1, 1},{2, 1},{3, 1},
               {-2, 2},{-1, 2},{0, 2},{1, 2},{2, 2},
                       {-1, 3},{0, 3},{1,3}
        };

        /// <summary>
        /// default constructor
        /// </summary>
        public Susan()
        {
        }

        /// <summary>
        /// used by clone to create a deep copy
        /// </summary>
        /// <param name="_susan"></param>
        internal Susan(Susan _susan)
        {
            this.m_aMask = _susan.m_aMask;
        }

        public List<Point> Points
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// executes this filter
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            double dBrightnessThreshold = 0.37f;
            Dictionary<Point, Color> aColorPoint = new Dictionary<Point, Color>();
            UnsafeBitmap bitmap = _bitmap;
            Color colorNucleus = Color.Transparent;
            Color color = Color.Transparent;
            
            int nUsan = 0;
            double dGeometricThreshold = 3 * 37 / 4.0f;
            int nPixels = 0;
            double dEdgeResponse = 0.0f;

            int nWidth = bitmap.Width;
            int nHeight = bitmap.Height;

            int y = 0;
            int x = 0;

            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    color = bitmap.GetPixel(x, y);
                    dGeometricThreshold = 0.0f;
                    nPixels = 0;
                    for (int i = 0; i < 37; i++)
                    {
                        int xTemp = x + m_aMask[i, 0];
                        int yTemp = y + m_aMask[i, 1];
                        if (xTemp < nWidth && yTemp < nHeight && xTemp > 0 && yTemp > 0)
                        {
                            Point ptTemp = new Point(xTemp, yTemp);
                            colorNucleus = bitmap.GetGrayPixel(xTemp, yTemp);
                            double dBrightness = Math.Abs(colorNucleus.GetBrightness() - color.GetBrightness());
                            double dBrightness2 = Math.Pow(Math.E, -(colorNucleus.GetBrightness() - color.GetBrightness()) / dBrightness);
                            if (!aColorPoint.ContainsKey(ptTemp))
                            {
                                if (dBrightness2 <= dBrightnessThreshold)
                                {
                                    aColorPoint.Add(ptTemp, Definitions.White);
                                    dGeometricThreshold += dBrightness2;
                                    nPixels++;
                                }
                                else
                                {
                                    aColorPoint.Add(ptTemp, Definitions.Black);
                                }
                            }
                        }
                    }
                    dEdgeResponse = dGeometricThreshold - nPixels;
                }
            }
            foreach(KeyValuePair<Point,Color> keyValuePair in aColorPoint)
            {
                bitmap.SetPixel(keyValuePair.Key.X, keyValuePair.Key.Y, keyValuePair.Value);
            }
            return _bitmap;
        }

        /// <summary>
        /// used to create a deep copy
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Susan(this);
        }
    }
}
